//package com.itheima.pinda.zuul.filter;
//
//import com.itheima.pinda.auth.client.properties.AuthClientProperties;
//import com.itheima.pinda.auth.client.utils.JwtTokenClientUtils;
//import com.itheima.pinda.auth.utils.JwtUserInfo;
//import com.itheima.pinda.authority.dto.auth.ResourceQueryDTO;
//import com.itheima.pinda.authority.entity.auth.Resource;
//import com.itheima.pinda.base.R;
//import com.itheima.pinda.common.adapter.IgnoreTokenConfig;
//import com.itheima.pinda.common.constant.CacheKey;
//import com.itheima.pinda.context.BaseContextConstants;
//import com.itheima.pinda.exception.BizException;
//import com.itheima.pinda.exception.code.ExceptionCode;
//import com.itheima.pinda.zuul.api.ResourceApi;
//import lombok.RequiredArgsConstructor;
//import lombok.extern.slf4j.Slf4j;
//import net.oschina.j2cache.CacheChannel;
//import net.oschina.j2cache.CacheObject;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.beans.factory.annotation.Qualifier;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.cloud.gateway.filter.GatewayFilterChain;
//import org.springframework.cloud.gateway.filter.GlobalFilter;
//import org.springframework.core.Ordered;
//import org.springframework.http.HttpMethod;
//import org.springframework.http.HttpStatus;
//import org.springframework.http.server.reactive.ServerHttpRequest;
//import org.springframework.stereotype.Component;
//import org.springframework.web.server.ServerWebExchange;
//import reactor.core.publisher.Mono;
//
//import javax.servlet.http.HttpServletRequest;
//import java.util.ArrayList;
//import java.util.List;
//import java.util.stream.Collectors;
//import java.util.stream.Stream;
//
///**
// * @Description: 网关过滤器
// * @Author: ysf
// * @CreateTime: 2024-11-15  16:35
// * @Version: 1.0
// */
//@Component
//@Slf4j
//public class BaseGatewayFilter implements GlobalFilter, Ordered {
//
//    @Value("${server.servlet.context-path}")
//    protected String zuulPrefix;
//
//    @Autowired
//    private JwtTokenClientUtils jwtTokenClientUtils;
//
//    @Autowired
//    AuthClientProperties authClientProperties;
//
//    @Autowired
//    CacheChannel cacheChannel;
//
//    @Qualifier("com.itheima.pinda.zuul.api.ResourceApi")
//    @Autowired
//    ResourceApi resourceApi;
//
//    @Override
//    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//        ServerHttpRequest request = exchange.getRequest();
//        String url = request.getURI().getPath();
//        HttpMethod method = request.getMethod();
//
//        // 去除zuulPrefix
//        url = url.substring(zuulPrefix.length());
//        // 去除第一个"/"之后的部分
//        int secondSlashIndex = url.indexOf("/", 1);
//        if (secondSlashIndex != -1) {
//            url = url.substring(secondSlashIndex);
//        }
//        //权限标识
//        String permission = method + url;
//
//        log.info("url---------------------------:{}",permission);
//
//        boolean ignoreToken = IgnoreTokenConfig.isIgnoreToken(url);
//        if (ignoreToken) {
//            // 如果需要忽略token，则直接放行
//            return chain.filter(exchange);
//        } else {
//            // 如果不需要忽略token，检查权限等逻辑
//            //1、获取token
//            String token = exchange.getRequest().getHeaders().getFirst(authClientProperties.getUser().getHeaderName());
//            log.info("token---------------------------:{}",token);
//
//            //解析token
//            JwtUserInfo userInfo = null;
//
//            try {
//                userInfo = jwtTokenClientUtils.getUserInfo(token);
//            } catch (BizException e) {
//                return errorResponse(exchange, e.getMessage(), e.getCode(), HttpStatus.OK);
//            } catch (Exception e) {
//                return errorResponse(exchange, ExceptionCode.JWT_PARSER_TOKEN_FAIL.getMsg(), R.FAIL_CODE, HttpStatus.OK);
//            }
//
//            //将用户信息封装进响应头
//            if (userInfo != null) {
//                addUserInfoToRequest(exchange, userInfo);
//            }
//
//
//            //2、鉴权
//
//            //从缓存中查询所有需要鉴权的资源，如果没有怎用openfeign调用api查询，并进行缓存
//            CacheObject cacheObject = cacheChannel.get(CacheKey.RESOURCE, CacheKey.RESOURCE_NEED_TO_CHECK);
//            List<String> list = null;
//            if (cacheObject.getValue() == null) {
//                list = resourceApi.list().getData();
//                if (list != null && list.size() > 0) {
//                    cacheChannel.set(CacheKey.RESOURCE, CacheKey.RESOURCE_NEED_TO_CHECK, list);
//                }
//            }
//            //判断当前请求的权限标识是否包含在权限资源中
//            long count = list.stream().filter((String s) -> {
//                return permission.startsWith(s);
//            }).count();
//
//            if (count == 0) {
//                return errorResponse(exchange, ExceptionCode.UNAUTHORIZED.getMsg(), ExceptionCode.UNAUTHORIZED.getCode(), HttpStatus.OK);
//            }
//
//            //如果包含当前的权限标识符，则从zuul header中取出用户id，根据用户id取出缓存中的用户拥有的权限，
//            String userId = exchange.getResponse().getHeaders().getFirst(BaseContextConstants.JWT_KEY_USER_ID);
//            CacheObject object = cacheChannel.get(CacheKey.USER_RESOURCE, userId);
//            List<String> userResource = (List<String>) object.getValue();
//            if (userResource == null) {
//                //从资源api查询
//                List<Resource> resourceData = resourceApi.visible(ResourceQueryDTO.builder().userId(Long.valueOf(userId)).build()).getData();
//                if (resourceData != null && resourceData.size() > 0) {
//                    userResource = resourceData.stream().map((Resource r) -> {
//                        return r.getMethod() + r.getUrl();
//                    }).collect(Collectors.toList());
//                    cacheChannel.set(CacheKey.USER_RESOURCE, userId, userResource);
//                }
//            }
//            //判断当前请求的权限标识是否包含在用户拥有的权限资源中
//            long counts = userResource.stream().filter((String s) -> {
//                return permission.startsWith(s);
//            }).count();
//
//            if (counts > 0) {
//                return chain.filter(exchange);
//            }else {
//                return errorResponse(exchange, ExceptionCode.UNAUTHORIZED.getMsg(), ExceptionCode.UNAUTHORIZED.getCode(), HttpStatus.OK);
//            }
//
//        }
//
//    }
//
//    private Mono<Void> errorResponse(ServerWebExchange exchange, String errMsg, int errCode, HttpStatus httpStatusCode) {
//        exchange.getResponse().setStatusCode(httpStatusCode);
//        exchange.getResponse().getHeaders().add("Content-Type", "application/json;charset=UTF-8");
//        String errorBody = R.fail(errCode, errMsg).toString();
//        return exchange.getResponse().writeWith(Mono.just(exchange.getResponse().bufferFactory().wrap(errorBody.getBytes())));
//    }
//
//
//    @Override
//    public int getOrder() {
//        return -1; // 设置过滤器的顺序
//    }
//
//    private void addUserInfoToRequest(ServerWebExchange exchange, JwtUserInfo userInfo) {
//        ServerHttpRequest request = exchange.mutate().build().getRequest();
//        addHeader(request, BaseContextConstants.JWT_KEY_NAME, userInfo.getName());
//        addHeader(request, BaseContextConstants.JWT_KEY_USER_ID, userInfo.getUserId());
//        addHeader(request, BaseContextConstants.JWT_KEY_STATION_ID, userInfo.getStationId());
//        addHeader(request, BaseContextConstants.JWT_KEY_ORG_ID, userInfo.getOrgId());
//        addHeader(request, BaseContextConstants.JWT_KEY_ACCOUNT, userInfo.getAccount());
//        exchange.mutate().request(request).build();
//    }
//
//    private void addHeader(ServerHttpRequest request, String name, Object value) {
//        if (value != null) {
//            request.mutate().header(name, value.toString()).build();
//        }
//    }
//}
